package com.ufo.asm;

import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class SumOfTwoNumbers {

    public int sum(int i, int m){
        return i+m;
    }

    private static byte[] generate(){
        ClassWriter cw = new ClassWriter(0);
        //对象头：版本号、修饰符、全类名、签名、父类、实现的接口
        cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC,
            "com/ufo/asm/AsmSum",null, "java/lang/Object",null);
        MethodVisitor mv=cw.visitMethod(Opcodes.ACC_PUBLIC,"sum","(II)I",null,null);
        mv.visitVarInsn(Opcodes.ILOAD,1);
        mv.visitVarInsn(Opcodes.ILOAD,2);
        mv.visitInsn(Opcodes.IADD);
        mv.visitInsn(Opcodes.IRETURN);
        mv.visitMaxs(2,3);
        mv.visitEnd();

        MethodVisitor methodVisitor = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); methodVisitor.visitInsn(Opcodes.RETURN); methodVisitor.visitMaxs(1, 1); methodVisitor.visitEnd();

        cw.visitEnd();
        return cw.toByteArray();
//        MethodVisitor mv=classwriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()v", null, null);

    }
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        byte[] bytes=generate();
//        outputClazz(bytes);
        MyClassLoader cl=new MyClassLoader();
        Class<?> testClass = cl.defineClass("com.ufo.asm.AsmSum",
            bytes);
        Object o = testClass.newInstance();
        Method m=testClass.getMethod("sum",int.class,int.class);
        System.out.println(m.invoke(o,1,2));
    }

    public static class MyClassLoader extends ClassLoader {
        public MyClassLoader() {
            super();
        }

        public MyClassLoader(ClassLoader cl) {
            super(cl);
        }

        public Class<?> defineClass(String name, byte[] b) {
            return defineClass(name, b, 0, b.length);
        }
    }
}
